home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / regs.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  45KB  |  1,131 lines

  1. /*  $VER: vbcc (regs.c) V0.4    */
  2. /*  Registerzuteilung           */
  3.  
  4. #include "opt.h"
  5.  
  6. static char FILE_[]=__FILE__;
  7.  
  8. #ifndef NO_OPTIMIZER
  9.  
  10. int (*savings)[MAXR+1],regu[MAXR+1];
  11. int *rvlist;
  12.  
  13. struct regp {int treg;struct Var *tvar,*tmp;};
  14. void do_load_parms(struct regp [],struct flowgraph *);
  15. void load_one_parm(int,int,struct Var *,struct Var *,struct flowgraph *);
  16.  
  17. int cmp_savings(const void *v1,const void *v2)
  18. /*  Vergleichsfkt, um rvlist nach savings zu sortieren  */
  19. {
  20.     return savings[*(int *)v2][0]-savings[*(int *)v1][0];
  21. }
  22. int entry_load(struct flowgraph *fg,int i)
  23. /*  Testet, ob die Variable in Register i am Anfang von Block fg geladen    */
  24. /*  werden muss, d.h. ein Vorgaenger sie nicht im selben Register hat.      */
  25. {
  26.     struct flowlist *lp;
  27.     lp=fg->in;
  28.     while(lp){
  29.         if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]&&BTST(lp->graph->av_out,fg->regv[i]->index)) return(1);
  30.         lp=lp->next;
  31.     }
  32.     return(0);
  33. }
  34.  
  35. int exit_save(struct flowgraph *fg,int i)
  36. /*  Testet, ob die Variable in Register i am Ende von Block fg gespeichert  */
  37. /*  werden muss, d.h. der Vorgaenger eines Nachfolgers nicht dieselbe       */
  38. /*  Variable im selben Register hat.                                        */
  39. {
  40.     struct flowlist *lp;
  41.     if((fg->normalout&&(!fg->end||fg->end->code!=BRA))&&BTST(fg->normalout->av_in,fg->regv[i]->index)){
  42.         if(fg->normalout->regv[i]!=fg->regv[i]) return(1);
  43.         lp=fg->normalout->in;
  44.         while(lp){
  45.             if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]) return(1);
  46.             lp=lp->next;
  47.         }
  48.     }
  49.     if(fg->branchout&&BTST(fg->branchout->av_in,fg->regv[i]->index)){
  50.         if(fg->branchout->regv[i]!=fg->regv[i]) return(1);
  51.         lp=fg->branchout->in;
  52.         while(lp){
  53.             if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]) return(1);
  54.             lp=lp->next;
  55.         }
  56.     }
  57.     return(0);
  58. }
  59. void load_reg_parms(struct flowgraph *fg)
  60. /*  Laedt Registerparameter, falls noetig.                              */
  61. {
  62.     int i,j; struct Var *v;
  63.     struct regp regp[MAXR+1]={0};
  64. /*     for(i=1;i<=MAXR;i++){ regp[i].treg=0;regp[i].tvar=0;} */
  65.     for(i=0;i<vcount-rcount;i++){
  66.         v=vilist[i];
  67.         if((v->flags®PARM)&&fg->regv[abs(v->reg)]!=v&&(BTST(fg->av_in,i)||(v->flags&USEDASADR))){
  68.       regp[abs(v->reg)].tvar=v;
  69.       for(j=1;j<=MAXR;j++)
  70.         if(fg->regv[j]==v) regp[abs(v->reg)].treg=j;
  71.     }
  72.     }
  73.     do_load_parms(regp,fg);
  74. }
  75.  
  76. void insert_regs(struct flowgraph *fg1)
  77. /*  Fuegt Registervariablen in die ICs ein.                             */
  78. {
  79.     int i;struct IC *p,*lic=0,*new;struct flowgraph *lfg=0,*fg;
  80.     if(DEBUG&9216) printf("inserting register variables\n");
  81.     fg=fg1;
  82.     while(fg){
  83.         if(DEBUG&8192) printf("block %d:\n",fg->index);
  84.         p=fg->start;
  85.         while(p){
  86.             for(i=1;i<=MAXR;i++){
  87.                 if(!fg->regv[i]) continue;
  88.                 if(p->code==ALLOCREG&&p->q1.reg==i) ierror(0);
  89.                 if((p->q1.flags&(VAR|DONTREGISTERIZE))==VAR&&p->q1.v==fg->regv[i]){
  90.                     p->q1.flags|=REG;
  91.                     p->q1.reg=i;
  92.                 }
  93.                 if((p->q2.flags&(VAR|DONTREGISTERIZE))==VAR&&p->q2.v==fg->regv[i]){
  94.                     p->q2.flags|=REG;
  95.                     p->q2.reg=i;
  96.                 }
  97.                 if((p->z.flags&(VAR|DONTREGISTERIZE))==VAR&&p->z.v==fg->regv[i]){
  98.                     p->z.flags|=REG;
  99.                     p->z.reg=i;
  100.                 }
  101.             }
  102.             if(DEBUG&8192) pric2(stdout,p);
  103.             if(p==fg->end) break;
  104.             p=p->next;
  105.         }
  106.         if(fg->start&&fg->start->code==LABEL) lic=fg->start;
  107.         for(i=1;i<=MAXR;i++){
  108.             if(fg->regv[i]){
  109.                 if(DEBUG&8192){
  110.                     printf("(%s),%ld assigned to %s\n",fg->regv[i]->identifier,zl2l(fg->regv[i]->offset),regnames[i]);
  111.                     if(BTST(fg->av_in,fg->regv[i]->index)) printf("active at the start of block\n");
  112.                     if(BTST(fg->av_out,fg->regv[i]->index)) printf("active at the end of block\n");
  113.                 }
  114.  
  115.                 if(BTST(fg->av_out,fg->regv[i]->index)){
  116.                 /*  Variable beim Austritt aktiv?   */
  117.                     if(exit_save(fg,i)){
  118.                         struct IC *tp;
  119.                         if(DEBUG&8192) printf("\thave to save it at end of block\n");
  120.                         new=mymalloc(ICS);
  121.                         new->line=0;
  122.                         new->file=0;
  123.                         new->code=ASSIGN;
  124.                         new->typf=fg->regv[i]->vtyp->flags;
  125.                         /*  cc  */
  126.                         if(new->typf==0) ierror(0);
  127.                         new->q1.flags=VAR|REG;
  128.                         new->q1.val.vlong=l2zl(0L);
  129.                         new->q1.v=fg->regv[i];
  130.                         new->q1.reg=i;
  131.                         new->q2.flags=0;
  132.                         new->q2.val.vlong=szof(fg->regv[i]->vtyp);
  133.                         new->z.flags=VAR|DONTREGISTERIZE;
  134.                         new->z.val.vlong=l2zl(0L);
  135.                         new->z.v=fg->regv[i];
  136.                         new->q1.am=new->q2.am=new->z.am=0;
  137.                         new->use_cnt=new->change_cnt=0;
  138.                         new->use_list=new->change_list=0;
  139.                         /*  Vor FREEREGs und evtl. Branch+COMPARE/TEST setzen   */
  140.                         if(fg->end){
  141.                             tp=fg->end;
  142.                             while(tp!=fg->start&&tp->code==FREEREG)
  143.                                 tp=tp->prev;
  144.                             if(tp&&tp->code>=BEQ&&tp->code<=BRA){
  145.                                 if(tp->code<BRA){
  146.                                     int c;
  147.                                     do{
  148.                                         tp=tp->prev;
  149.                                         c=tp->code;
  150.                                         if(c!=FREEREG&&c!=COMPARE&&c!=TEST) ierror(0);
  151.                                     }while(c!=COMPARE&&c!=TEST);
  152.                                 }
  153.                                 tp=tp->prev;
  154.                             }
  155.                         }else tp=lic;
  156.                         insert_IC_fg(fg,tp,new);
  157.                     }
  158.                 }
  159.                 if(BTST(fg->av_in,fg->regv[i]->index)){
  160.                     if((fg==fg1||entry_load(fg,i))&&(fg!=fg1||!(fg->regv[i]->flags®PARM))){
  161.                         if(DEBUG&8192) printf("\thave to load it at start of block\n");
  162.  
  163.                         new=mymalloc(ICS);
  164.                         new->line=0;
  165.                         new->file=0;
  166.                         new->code=ASSIGN;
  167.                         new->typf=fg->regv[i]->vtyp->flags;
  168.                         /*  cc  */
  169.                         if(new->typf==0) ierror(0);
  170.                         new->q1.flags=VAR|DONTREGISTERIZE;
  171.                         new->q1.val.vlong=l2zl(0L);
  172.                         new->q1.v=fg->regv[i];
  173.                         new->q2.flags=0;
  174.                         new->q2.val.vlong=szof(fg->regv[i]->vtyp);
  175.                         new->z.flags=VAR|REG;
  176.                         new->z.val.vlong=l2zl(0L);
  177.                         new->z.v=fg->regv[i];
  178.                         new->z.reg=i;
  179.                         new->q1.am=new->q2.am=new->z.am=0;
  180.                         new->use_cnt=new->change_cnt=0;
  181.                         new->use_list=new->change_list=0;
  182.                         insert_IC_fg(fg,lic,new);
  183.                     }
  184.                 }
  185.                 if(!lfg||!lfg->regv[i]) insert_allocreg(fg,lic,ALLOCREG,i);
  186.                 if(!fg->normalout||!fg->normalout->regv[i])
  187.                     insert_allocreg(fg,fg->end?fg->end:lic,FREEREG,i);
  188.             }
  189.         }
  190.         if(fg->end) lic=fg->end;
  191.         lfg=fg;
  192.         fg=fg->normalout;
  193.     }
  194.     load_reg_parms(fg1);
  195. }
  196.  
  197. void do_loop_regs(struct flowgraph *start,struct flowgraph *end)
  198. /*  Macht die Variablenzuweisung in Schleife start-end.                 */
  199. /*  Wenn end==0 Registerzuweisung fuer die ganze Funktion, ansonsten    */
  200. /*  fuer die Schleife, die zum Header start gehoert.                    */
  201. {
  202.     struct flowgraph *g;
  203.     int i,r;
  204.     struct Var *lregs[MAXR+1]={0};
  205.     unsigned char rused[(MAXR+CHAR_BIT)/CHAR_BIT];
  206.     /*  Berechnen, wieviel ungefaehr eingespart wird, wenn eine Variable    */
  207.     /*  fuer diese Schleife in einem best. Register gehalten wird.          */
  208.     /*  Die savings in einer Schleife werden multipliziert, um das          */
  209.     /*  Laden/Speichern ausserhalb der Schleife geringer zu wichten.        */
  210. /*    if(end&&(!g->normalout||!g->normalout->loopend||g->normalout->loopend->normalout->index!=-2)) ierror(0);*/
  211.     /*  alle auf 0  */
  212.     for(i=0;i<vcount-rcount;i++){
  213.         for(r=1;r<=MAXR;r++){
  214.             savings[i][r]=0;
  215.         }
  216.     }
  217.     if(end){
  218.         struct Var *v;
  219.         /*  Evtl. Kosten fuers Laden/Speichern beim Ein-/Austritt in die    */
  220.         /*  Schleife.                                                       */
  221.         end=start->normalout->loopend;
  222.         g=end->normalout;
  223.         if(DEBUG&9216) printf("assigning regs to blocks %d to %d\n",start->normalout->index,end->index);
  224.         /*  Werte modifizieren, falls Variable am Anfang/Ende der Schleife  */
  225.         /*  geladen/gespeichert werden muss.                                */
  226.         for(i=0;i<vcount-rcount;i++){
  227.             v=vilist[i];
  228.             if(BTST(start->av_in,i)){
  229.                 for(r=1;r<=MAXR;r++)
  230.                     if(start->regv[r]!=v) savings[i][r]--;
  231.             }
  232.             if(BTST(g->av_out,i)){
  233.                 for(r=1;r<=MAXR;r++)
  234.                     if(g->regv[r]!=v) savings[i][r]--;
  235.             }
  236.         }
  237.         /*  Werte modifizieren, falls eine andere Variable gespeichert oder */
  238.         /*  geladen werden muss. Hmm..stimmt das so?                        */
  239.         for(r=1;r<=MAXR;r++){
  240.             v=start->regv[r];
  241.             if(v&&BTST(start->av_in,v->index)){
  242.                 for(i=0;i<vcount-rcount;i++)
  243.                     if(v->index!=i) savings[i][r]--;
  244.             }
  245.             if(v&&BTST(g->av_out,v->index)){
  246.                 for(i=0;i<vcount-rcount;i++)
  247.                     if(v->index!=i) savings[i][r]--;
  248.             }
  249.         }
  250.         g=start->normalout;
  251.     }else{
  252.         /*  Bei Registervergabe fuer die ganze Funktion muessen alle beim   */
  253.         /*  Eintritt der Funktion aktiven Variablen geladen werden.         */
  254.         if(DEBUG&9216) printf("assigning regs to whole function\n");
  255.         for(i=0;i<vcount-rcount;i++){
  256.             if(BTST(start->av_in,i)){
  257.                 int pr=abs(vilist[i]->reg);
  258.                 for(r=1;r<=MAXR;r++){
  259.                     if(pr==0||!regok(r,vilist[i]->vtyp->flags,0)||regsa[r]){
  260.                         savings[i][r]-=8;
  261.                     }else{
  262.                         if(r==pr) savings[i][r]+=8; else savings[i][r]+=4;
  263.                     }
  264.                 }
  265.             }
  266.         }
  267.         g=start;
  268.     }
  269.     if(DEBUG&9216) printf("calculating approximate savings\n");
  270.  
  271.     for(;g;g=g->normalout){
  272.         struct IC *p;struct Var *v;
  273.         int t,vt;
  274.         if(g->calls>0){
  275.         /*  bei Funktionsaufrufen muessen Scratchregister gespeichert werden */
  276.             for(r=1;r<=MAXR;r++)
  277.                 if(regscratch[r])
  278.                     for(i=0;i<vcount-rcount;i++) savings[i][r]-=g->calls*16;
  279.         }
  280.         /*  Wenn das Register in dem Block benutzt wird, muss man es retten */
  281.         for(r=1;r<=MAXR;r++){
  282.             if(BTST(g->regused,r)){
  283.                 int vi;
  284.                 if(g->regv[r]) vi=g->regv[r]->index; else vi=-1;
  285.                 for(i=0;i<vcount-rcount;i++)
  286.                     if(vi!=i) savings[i][r]-=16;
  287.             }
  288.         }
  289.         for(p=g->start;p;p=p->next){
  290.             if((p->q1.flags&(VAR|VARADR|REG))==VAR){
  291.                 v=p->q1.v;
  292.                 if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  293.                     vt=v->vtyp->flags&NU;
  294.                     i=v->index;
  295.                     if(p->q1.flags&DREFOBJ) t=p->typf&NU; else t=0;
  296.                     for(r=1;r<=MAXR;r++){
  297.                         if(!regsa[r]&&!BTST(g->regused,r)){
  298.                             /*  extra saving, falls passendes Reg fuer DREF */
  299.                             if(t&®ok(r,vt,t)) savings[i][r]+=8;
  300.                             if(regok(r,vt,0)) savings[i][r]+=8;
  301.                         }
  302.                     }
  303.                 }
  304.             }
  305.             if((p->q2.flags&(VAR|VARADR|REG))==VAR){
  306.                 v=p->q2.v;
  307.                 if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  308.                     vt=v->vtyp->flags&NU;
  309.                     i=v->index;
  310.                     if(p->q2.flags&DREFOBJ) t=p->typf&NU; else t=0;
  311.                     for(r=1;r<=MAXR;r++){
  312.                         if(!regsa[r]&&!BTST(g->regused,r)){
  313.                             /*  extra saving, falls passendes Reg fuer DREF */
  314.                             if(t&®ok(r,vt,t)) savings[i][r]+=8;
  315.                             if(regok(r,vt,0)) savings[i][r]+=8;
  316.                         }
  317.                     }
  318.                 }
  319.             }
  320.             if((p->z.flags&(VAR|VARADR|REG))==VAR){
  321.                 v=p->z.v;
  322.                 if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  323.                     vt=v->vtyp->flags&NU;
  324.                     i=v->index;
  325.                     if(p->z.flags&DREFOBJ) t=p->typf&NU; else t=0;
  326.                     for(r=1;r<=MAXR;r++){
  327.                         if(!regsa[r]&&!BTST(g->regused,r)){
  328.                             /*  extra saving, falls passendes Reg fuer DREF */
  329.                             if(t&®ok(r,vt,t)) savings[i][r]+=8;
  330.                             if(regok(r,vt,0)) savings[i][r]+=8;
  331.                         }
  332.                     }
  333.                 }
  334.             }
  335.             if(p==g->end) break;
  336.         }
  337.         if(g==end) break;
  338.     }
  339.     /*  Maximum ermitteln   */
  340.     for(i=0;i<vcount-rcount;i++){
  341.         int m=0;
  342.         for(r=1;r<=MAXR;r++){
  343.             /*  Falls Variable in best. Register muss.  */
  344.             if(r==abs(vilist[i]->reg)&&!(vilist[i]->flags®PARM)) savings[i][r]*=4;
  345.             if(savings[i][r]>m) m=savings[i][r];
  346.         }
  347.         savings[i][0]=m;
  348.     }
  349.  
  350.     if(DEBUG&8192){
  351.         for(i=0;i<vcount-rcount;i++){
  352.             printf("(%s),%ld(best=%d):\n",vilist[i]->identifier,zl2l(vilist[i]->offset),savings[i][0]);
  353.             for(r=1;r<=MAXR;r++)
  354.                 printf("%s=%d ",regnames[r],savings[i][r]);
  355.             printf("\n");
  356.         }
  357.     }
  358.     /*  Suchen, welche Variablen/Registerkombination das beste Ergebnis */
  359.     /*  liefert. Nur angenaehert, da sonst wohl zu aufwendig. Simplex?  */
  360.     memset(rused,0,(MAXR+CHAR_BIT)/CHAR_BIT);
  361.     for(i=0;i<vcount-rcount;i++) rvlist[i]=i;
  362.     qsort(rvlist,vcount-rcount,sizeof(*rvlist),cmp_savings);
  363.     for(i=0;i<vcount-rcount;i++){
  364.         int use,m=0,vi;
  365.         vi=rvlist[i];
  366.         if(vilist[vi]->flags&USEDASADR) continue;
  367.         if(DEBUG&8192) printf("%d: (%s),%ld(best=%d)\n",i,vilist[vi]->identifier,zl2l(vilist[vi]->offset),savings[vi][0]);
  368.         for(r=1;r<=MAXR;r++){
  369.             if(!lregs[r]&&savings[vi][r]>m){
  370.                 m=savings[vi][r];
  371.                 use=r;
  372.                 if(m==savings[vi][0]) break;
  373.             }
  374.         }
  375.         if(m>0){
  376.             if(DEBUG&9216) printf("assigned (%s),%ld to %s, saving=%d\n",vilist[vi]->identifier,zl2l(vilist[vi]->offset),regnames[use],m);
  377.             lregs[use]=vilist[vi];
  378.             BSET(rused,use);
  379.         }
  380.     }
  381.     /*  Registervariablen in alle Bloecke der Schleife eintragen    */
  382.     /*  dabei beruecksichtigen, dass sie in manchen Bloecken nicht  */
  383.     /*  in Register kommen koennen, wenn das Register da schon von  */
  384.     /*  local_regs benutzt wird                                     */
  385.     /*  Gegebenenfalls auch in Header/Footer einer Schleife         */
  386.     /*  eintragen.                                                  */
  387.     if(DEBUG&9216) printf("propagate register vars\n");
  388.     for(g=start;g;g=g->normalout){
  389.         for(r=1;r<=MAXR;r++){
  390.             if(lregs[r]&&!BTST(g->regused,r)){
  391.                 /*  Falls Variable schon in anderem Register, loeschen  */
  392.                 for(i=1;i<=MAXR;i++){
  393.                     if(g->regv[i]==lregs[r]) g->regv[i]=0;
  394.                 }
  395.                 g->regv[r]=lregs[r];
  396.             }
  397.         }
  398.         if(end&&g==end->normalout) break;
  399.     }
  400. }
  401. void block_regs(struct flowgraph *fg)
  402. /*  macht die Variablenzuweisung fuer einzelne Bloecke  */
  403. {
  404.     struct flowgraph *g,**fgp;
  405.     int i,r,changed,fgz;
  406.     if(DEBUG&9216) printf("block_regs\n");
  407.  
  408.     savings=mymalloc((vcount-rcount)*sizeof(*savings));
  409.     rvlist=mymalloc((vcount-rcount)*sizeof(*rvlist));
  410.  
  411.     /*  Array auf Bloecke im Flussgraphen mangels doppelter Verkettung  */
  412.     fgp=mymalloc(basic_blocks*sizeof(*fgp));
  413.     g=fg;fgz=0;
  414.     while(g){
  415.         fgp[fgz]=g;fgz++;
  416.         g=g->normalout;
  417.     }
  418.     if(fgz>basic_blocks) ierror(0); else basic_blocks=fgz;
  419.     /*  alle auf 0  */
  420.     do{
  421.         changed=0;
  422.         if(DEBUG&9216) printf("block_regs pass\n");
  423.         for(fgz=basic_blocks-1;fgz>=0;fgz--){
  424.             struct IC *p;struct Var *v;struct flowlist *lp;
  425.             int t,vt;
  426.             g=fgp[fgz];
  427.             if(DEBUG&8192) printf("assigning regs to block %d\n",g->index);
  428.             /*  berechnen, wieviel ungefaehr eingespart wird, wenn eine Variable    */
  429.             /*  fuer diesen Block in einem best. Register gehalten wird             */
  430.             if(DEBUG&8192) printf("calculating approximate savings\n");
  431.  
  432.             for(i=0;i<vcount-rcount;i++){
  433.                 for(r=1;r<=MAXR;r++){
  434.                     if(!g->regv[r]||g->regv[r]->index!=i){
  435.                         int w=0;
  436.                         /*  Variable muss evtl. geladen/gespeichert werden  */
  437.                         if(BTST(g->av_in,i)) w--;
  438.                         if(BTST(g->av_out,i)) w--;
  439.                         savings[i][r]=w;
  440.                     }
  441.                 }
  442.             }
  443.             if(g->calls>0){
  444.             /*  bei Funktionsaufrufen muessen Scratchregister gespeichert werden */
  445.                 for(r=1;r<=MAXR;r++)
  446.                     if(regscratch[r])
  447.                         for(i=0;i<vcount-rcount;i++) savings[i][r]-=g->calls*2;
  448.             }
  449.             /*  Wenn Vorgaenger/Nachfolger selbe Variable im selben */
  450.             /*  Register hat, entfaellt Laden/Speichern in diesem   */
  451.             /*  Block und vermutlich auch im Vorgaenger/Nachfolger  */
  452.             /*  nicht immer, aber naeherungsweise...                */
  453.             lp=g->in;
  454.             while(lp){
  455.                 if(lp->graph){
  456.                     for(r=1;r<=MAXR;r++){
  457.                         if(lp->graph->regv[r]&&BTST(g->av_in,lp->graph->regv[r]->index)) savings[lp->graph->regv[r]->index][r]+=2;
  458.                     }
  459.                 }
  460.                 lp=lp->next;
  461.             }
  462.             if(g->branchout){
  463.                 for(r=1;r<=MAXR;r++){
  464.                     if(g->branchout->regv[r]&&BTST(g->av_out,g->branchout->regv[r]->index)) savings[g->branchout->regv[r]->index][r]+=2;
  465.                 }
  466.             }
  467.             if(g->normalout&&(!g->normalout->end||g->normalout->end->code!=BRA)){
  468.                 for(r=1;r<=MAXR;r++){
  469.                     if(g->normalout->regv[r]&&BTST(g->av_out,g->normalout->regv[r]->index)) savings[g->normalout->regv[r]->index][r]+=2;
  470.                 }
  471.             }
  472.  
  473.             p=g->start;
  474.             while(p){
  475.                 if((p->q1.flags&(VAR|VARADR|REG))==VAR){
  476.                     v=p->q1.v;
  477.                     if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  478.                         vt=v->vtyp->flags&NU;
  479.                         i=v->index;
  480.                         if(p->q1.flags&DREFOBJ) t=p->typf&NU; else t=0;
  481.                         for(r=1;r<=MAXR;r++){
  482.                             if(!regsa[r]&&!BTST(g->regused,r)){
  483.                                 /*  extra saving, falls passendes Reg fuer DREF */
  484.                                 if(t&®ok(r,vt,t)) savings[i][r]++;
  485.                                 if(regok(r,vt,0)) savings[i][r]++;
  486.                             }
  487.                         }
  488.                     }
  489.                 }
  490.                 if((p->q2.flags&(VAR|VARADR|REG))==VAR){
  491.                     v=p->q2.v;
  492.                     if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  493.                         vt=v->vtyp->flags&NU;
  494.                         i=v->index;
  495.                         if(p->q2.flags&DREFOBJ) t=p->typf&NU; else t=0;
  496.                         for(r=1;r<=MAXR;r++){
  497.                             if(!regsa[r]&&!BTST(g->regused,r)){
  498.                                 /*  extra saving, falls passendes Reg fuer DREF */
  499.                                 if(t&®ok(r,vt,t)) savings[i][r]++;
  500.                                 if(regok(r,vt,0)) savings[i][r]++;
  501.                             }
  502.                         }
  503.                     }
  504.                 }
  505.                 if((p->z.flags&(VAR|VARADR|REG))==VAR){
  506.                     v=p->z.v;
  507.                     if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
  508.                         vt=v->vtyp->flags&NU;
  509.                         i=v->index;
  510.                         if(p->z.flags&DREFOBJ) t=p->typf&NU; else t=0;
  511.                         for(r=1;r<=MAXR;r++){
  512.                             if(!regsa[r]&&!BTST(g->regused,r)){
  513.                                 /*  extra saving, falls passendes Reg fuer DREF */
  514.                                 if(t&®ok(r,vt,t)) savings[i][r]++;
  515.                                 if(regok(r,vt,0)) savings[i][r]++;
  516.                             }
  517.                         }
  518.                     }
  519.                 }
  520.                 if(p==g->end) break;
  521.                 p=p->next;
  522.             }
  523.             /*  moegliche Kandidaten suchen; muss nicht immer die beste */
  524.             /*  Kombination finden, sollte aber bei lokaler Vergabe     */
  525.             /*  selten einen Unterschied machen                         */
  526.             for(r=1;r<=MAXR;r++){
  527.                 if(g->regv[r]||BTST(g->regused,r)) continue;
  528.                 for(i=0;i<vcount-rcount;i++){
  529.                     if(savings[i][r]>0){
  530.                         int flag;struct Var *v=vilist[i];
  531.                         /*  Variable schon in anderem Register? */
  532.                         for(flag=1;flag<=MAXR;flag++)
  533.                             if(g->regv[flag]==v){flag=-1;break;}
  534.                         if(flag>0){
  535.                             if(DEBUG&9216) printf("assigned (%s),%ld to %s; saving=%d\n",vilist[i]->identifier,zl2l(vilist[i]->offset),regnames[r],savings[i][r]);
  536.                             g->regv[r]=vilist[i];
  537.                             changed=1;
  538.                             break;
  539.                         }
  540.                     }
  541.                 }
  542.             }
  543.         }
  544.     }while(changed);
  545.     /*  jetzt nochmal globale Register vergeben */
  546. /*    do_loop_regs(fgp[0],fgp[basic_blocks-1]);*/
  547.  
  548.     free(fgp);
  549.     free(rvlist);
  550.     free(savings);
  551. }
  552.  
  553. void loop_regs(struct flowgraph *fg)
  554. /*  weist Variablen in Schleifen Register zu    */
  555. {
  556.     struct flowgraph *g;
  557.     if(DEBUG&9216) printf("assigning regs to function\n");
  558.     savings=mymalloc((vcount-rcount)*sizeof(*savings));
  559.     rvlist=mymalloc((vcount-rcount)*sizeof(*rvlist));
  560.     do_loop_regs(fg,0);
  561.     if(DEBUG&9216) printf("assigning regs in loops\n");
  562.     for(g=fg;g;g=g->normalout){
  563.         if(g->index==-1) do_loop_regs(g,g);
  564.     }
  565.     free(rvlist);
  566.     free(savings);
  567. }
  568. void insert_allocreg(struct flowgraph *fg,struct IC *p,int code,int reg)
  569. /*  Fuegt ein ALLOCREG/FREEREG (in code) hinter p ein - bei p==0 in */
  570. /*  first_ic.                                                       */
  571. {
  572.     struct IC *new=mymalloc(ICS);
  573.     /*    printf("%s %s",code==FREEREG?"freereg":"allocreg",regnames[reg]);pric2(stdout,p);*/
  574.     new->line=0;
  575.     new->file=0;
  576.     BSET(fg->regused,reg);
  577.     regused[reg]=1;
  578.     new->code=code;
  579.     new->typf=0;
  580.     new->q1.am=new->q2.am=new->z.am=0;
  581.     new->q1.flags=REG;
  582.     new->q1.reg=reg;
  583.     new->q2.flags=new->z.flags=0;
  584.     new->use_cnt=new->change_cnt=0;
  585.     new->use_list=new->change_list=0;
  586.     insert_IC_fg(fg,p,new);
  587. }
  588.  
  589. struct Var *lregv[MAXR+1];
  590. struct flowgraph *lfg;
  591.  
  592. void free_hreg(struct flowgraph *fg,struct IC *p,int reg,int mustr)
  593. /*  Macht das Register reg frei, damit es als lokale Variable im IC p   */
  594. /*  zur Verfuegung steht. Wenn mustr!=0, muss das Register unbedingt    */
  595. /*  freigemacht werden, ansonsten kann davon abgesehen werden.          */
  596. {
  597.     struct IC *m,*first;struct Var *v;
  598.     int preg[MAXR+1]={0},calls=0,rreg,i;
  599.     first=0; v=lregv[reg];
  600.     if(!v) ierror(0);
  601.     if(DEBUG&8192) printf("free_hreg %s,%s,%d\n",regnames[reg],v->identifier,mustr);
  602.     if(v->reg&&!*v->identifier) ierror(0);
  603.     for(m=p;m;m=m->next){
  604.         if(m->code==CALL) calls++;
  605.         if(m->code==ALLOCREG){
  606.             preg[m->q1.reg]=1;
  607.             if(m->q1.reg==reg) ierror(0);
  608.         }
  609.         if(m->code==FREEREG){
  610.             preg[m->q1.reg]=1;
  611.             if(m->q1.reg==reg) break;
  612.         }
  613.         if(!USEQ2ASZ){
  614.             if((m->q2.flags&VAR)&&m->q2.v==v&&(m->z.flags&(REG|DREFOBJ))==REG&&
  615.                (!(m->z.flags&VAR)||m->z.v!=v))
  616.                 preg[m->z.reg]=1;
  617.         }
  618.         if(((m->q1.flags&VAR)&&m->q1.v==v)||
  619.            ((m->q2.flags&VAR)&&m->q2.v==v)||
  620.            ((m->z.flags&(VAR|DREFOBJ))==(VAR|DREFOBJ)&&m->z.v==v))
  621.             first=m;
  622. /*        if((m->z.flags&(REG|DREFOBJ))==REG&&m->z.reg==reg) break;*/
  623.     }
  624.     if(!first) {pric(stdout,p);ierror(0);}
  625.     for(rreg=0,i=1;i<=MAXR;i++){
  626.         if(preg[i]||regu[i]||regsa[i]||!regok(i,v->vtyp->flags,0)) continue;
  627.         if(calls==0&®scratch[i]){rreg=i;break;}
  628.         if(calls>0&&!regscratch[i]){rreg=i;break;}
  629.         if(calls==0&&mustr) rreg=i;
  630.     }
  631.     if(!rreg&&!mustr) return;
  632.     for(m=p;m!=first->next;m=m->next){
  633.         if((m->q1.flags&VAR)&&m->q1.v==v)
  634.             {if(!rreg) m->q1.flags&=~REG; else m->q1.reg=rreg;}
  635.         if((m->q2.flags&VAR)&&m->q2.v==v)
  636.             {if(!rreg) m->q2.flags&=~REG; else m->q2.reg=rreg;}
  637.         if((m->z.flags&VAR)&&m->z.v==v)
  638.             {if(!rreg) m->z.flags&=~REG; else m->z.reg=rreg;}
  639.     }
  640.     if(rreg){lregv[rreg]=lregv[reg];regused[rreg]=1;regu[rreg]=1;BSET(fg->regused,rreg);}
  641.     lregv[reg]=0;regu[reg]=0;
  642.  
  643.     for(m=first->next;m&&m->code==FREEREG;m=m->next){
  644.         if(m->q1.reg==reg){
  645.             if(!rreg) remove_IC_fg(fg,m); else m->q1.reg=rreg;
  646. /*            if(rreg) insert_allocreg(fg,first,FREEREG,rreg);*/
  647.             return;
  648.         }
  649.     }
  650.     insert_allocreg(fg,first->prev,ALLOCREG,reg);
  651.     if(rreg) insert_allocreg(fg,first,FREEREG,rreg);
  652. }
  653. int replace_local_reg(struct obj *o)
  654. /*  tested, ob o eine Scratch-Variable ist und ersetzt sie gegebenenfalls   */
  655. {
  656.     int i;struct Var *v;
  657.     if((o->flags&(VAR|REG|VARADR))==VAR){
  658.         v=o->v;i=v->index;
  659.         if(BTST(lfg->av_kill,i)&&!BTST(lfg->av_out,i)){
  660.             for(i=1;i<=MAXR;i++){
  661.                 if(lregv[i]==v){
  662.                     o->flags|=(REG|SCRATCH);
  663. /*                    o->flags&=~VAR;*/
  664.                     o->reg=i;
  665.                     return(i);
  666.                 }
  667.             }
  668.         }
  669.     }
  670.     return(0);
  671. }
  672. void local_combine(struct flowgraph *fg)
  673. /*  Versucht, Zuweisungen der Form (x)->tmp in ein direkt folgendes IC */
  674. /*  einzugliedern. Nur einfache Tests, da nur loads eliminiert werden  */
  675. /*  sollen, die zum leichten Erkennen per cse explizit wurden.         */
  676. {
  677.   struct IC *p,*pprev;int i,cl;
  678.   unsigned char *used=mymalloc(vsize);
  679.   if(DEBUG&1024) printf("local combining\n");
  680.   for(;fg;fg=fg->normalout){
  681.     memcpy(used,fg->av_out,vsize);
  682.     for(p=fg->end;p;p=p->prev){
  683.       if((pprev=p->prev)&&pprev->code==ASSIGN&&zleqto(pprev->q2.val.vlong,sizetab[pprev->typf])
  684.      &&(pprev->q1.flags&DREFOBJ)&&(pprev->z.flags&(VAR|DREFOBJ))==VAR
  685.      &&!BTST(used,(i=pprev->z.v->index))&&pprev->z.v->storage_class==AUTO
  686.      &&!(pprev->z.v->flags&USEDASADR)){
  687.     cl=0;
  688.     if((p->z.flags&VAR)&&p->z.v->index==i) cl=4;
  689.     if((p->q1.flags&(VAR|DREFOBJ))==VAR){
  690.       if(p->q1.v->index==i&&zleqto(p->q1.val.vlong,p->prev->z.val.vlong))
  691.         cl|=1;
  692.     }
  693.     if((p->q2.flags&(VAR|DREFOBJ))==VAR){
  694.       if(p->q2.v->index==i&&zleqto(p->q2.val.vlong,p->prev->z.val.vlong))
  695.         cl|=2;
  696.     }
  697.     if(cl==1||cl==2){
  698. #if 0
  699. printf("cl=%d USEQ2ASZ=%d,cmp=%d\n",cl,USEQ2ASZ,compare_objs(&p->prev->q1,&p->z,p->typf));
  700. printf("f1=%p,f2=%p\n",p->prev->q1.v,p->z.v);
  701. probj(stdout,&p->prev->q1,p->typf);printf("\n");
  702. probj(stdout,&p->z,p->typf);printf("\n");
  703. #endif
  704.       if(cl!=2||USEQ2ASZ||compare_objs(&p->prev->q1,&p->z,p->typf)){
  705.         if(DEBUG&1024){printf("local combine:\n");pric2(stdout,p->prev);pric2(stdout,p);}
  706.         if(cl==1) p->q1=p->prev->q1; else p->q2=p->prev->q1;
  707.         p->prev->code=NOP;
  708.         p->prev->q1.flags=p->prev->z.flags=0;
  709.       }
  710.     }
  711.       }
  712.       if(p==fg->start) break;
  713.       if(p->q1.flags&VAR) BSET(used,p->q1.v->index);
  714.       if(p->q2.flags&VAR) BSET(used,p->q2.v->index);
  715.       if(p->z.flags&VAR) BSET(used,p->z.v->index);
  716.     }
  717.   }
  718. }
  719.  
  720. void local_regs(struct flowgraph *fg)
  721. /*  versucht Variablen, die nur innerhalb eines Basic Blocks benutzt    */
  722. /*  werden (kill==true und out==false), Register zuzuweisen.            */
  723. {
  724.     struct IC *p;
  725.     int i,j,t,r,nr,mustalloc;
  726.     unsigned char *inmem=mymalloc(vsize);
  727.     if(DEBUG&9216) printf("assigning temporary variables to registers\n");
  728.     memset(inmem,0,vsize);
  729.     lfg=fg;
  730.     while(lfg){
  731.         if(DEBUG&1024) printf("block %d\n",lfg->index);
  732.         for(i=1;i<=MAXR;i++){lregv[i]=0; regu[i]=regsa[i]; lfg->regv[i]=0;}
  733.         memset(&lfg->regused,0,(MAXR+CHAR_BIT)/CHAR_BIT);
  734.         lfg->calls=0;
  735.         p=lfg->end;
  736.         while(p){
  737.             nr=0;
  738.             i=replace_local_reg(&p->z);
  739.             if((p->z.flags&(VAR|DREFOBJ))==VAR){
  740.                 if(i){
  741.                     lregv[i]=0;regu[i]--;
  742.                     nr=i;mustalloc=1;
  743.                     if(DEBUG&8192) printf("regu[%s] decremented to %d\n",regnames[i],regu[i]);
  744.                 }else{
  745.                     BCLR(inmem,p->z.v->index);
  746.                 }
  747.             }
  748.             if(p->code!=ADDRESS){
  749.                 if(replace_local_reg(&p->q1)==nr) mustalloc=0;
  750.                 if(replace_local_reg(&p->q2)==nr) mustalloc=0;
  751.             }
  752.             /*  hier wegen USEQ2ASZ aufpassen; kommutative ICs sollten so   */
  753.             /*  angeordnet werden, dass ein evtl. Register rechts steht     */
  754.             if((p->q2.flags&(VAR|REG|VARADR))==VAR&&!(p->q2.v->flags&USEDASADR)&&!(p->q2.v->vtyp->flags&VOLATILE)&&(p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER)){
  755.                 j=p->q2.v->index;
  756.                 if(BTST(lfg->av_kill,j)&&!BTST(lfg->av_out,j)&&!BTST(inmem,j)){
  757.                     t=p->q2.v->vtyp->flags;
  758.                     if(USEQ2ASZ&&nr&®ok(nr,t,0)&&!regu[nr]&&!regsa[nr]&&(!(p->q2.flags&DREFOBJ)||regok(nr,t,p->typf))) r=nr; else r=0;
  759.                     if(p->q2.v->reg){ r=p->q2.v->reg;if(regu[r]) free_hreg(lfg,p,r,1);}
  760.                     for(i=0;r==0&&i<=MAXR;i++){
  761.                         if(!regu[i]&&!regsa[i]&®ok(i,t,0)&&(USEQ2ASZ||i!=nr)) {r=i;break;}
  762.                     }
  763.                     if(r){
  764.                         if(r!=nr) insert_allocreg(lfg,p,FREEREG,r);
  765.                             else mustalloc=0;
  766.                         lregv[r]=p->q2.v;regused[r]=regu[r]=1;
  767.                         if(replace_local_reg(&p->q2)!=r) ierror(0);
  768.                         replace_local_reg(&p->q1);
  769.                         replace_local_reg(&p->z);
  770.                         if((DEBUG&9216)&&*p->q2.v->identifier) printf("temporary <%s> assigned to %s\n",p->q2.v->identifier,regnames[r]);
  771.                         if(DEBUG&8192) printf("temporary <%s> assigned to %s\n",p->q2.v->identifier,regnames[r]);
  772.                     }else BSET(inmem,j);
  773.                 }
  774.             }
  775.             if((p->z.flags&(VAR|REG|DREFOBJ))==(VAR|DREFOBJ)&&!(p->z.v->flags&USEDASADR)&&!(p->z.v->vtyp->flags&VOLATILE)&&(p->z.v->storage_class==AUTO||p->z.v->storage_class==REGISTER)){
  776.                 j=p->z.v->index;
  777.                 if(BTST(lfg->av_kill,j)&&!BTST(lfg->av_out,j)&&!BTST(inmem,j)){
  778.                     r=0;
  779.                     if(p->z.v->reg){ r=abs(p->z.v->reg);if(regu[r]) free_hreg(lfg,p,r,1);}
  780.                     for(i=0,t=p->z.v->vtyp->flags;i<=MAXR;i++){
  781.                         if(!regu[i]&&!regsa[i]&®ok(i,t,0)) {r=i;break;}
  782.                     }
  783.                     if(r){
  784.                         insert_allocreg(lfg,p,FREEREG,r);
  785.                         lregv[r]=p->z.v;regused[r]=regu[r]=1;
  786.                         if(replace_local_reg(&p->z)!=r){
  787.                             for(i=1;i<=MAXR;i++) if(lregv[i]) printf("%d:%s=%s(%p)\n",i,regnames[i],lregv[i]->identifier,(void*)lregv[i]);
  788.                             ierror(r);}
  789.                         replace_local_reg(&p->q1);
  790.                         if((DEBUG&9216)&&*p->z.v->identifier) printf("temporary <%s> assigned to %s\n",p->z.v->identifier,regnames[r]);
  791.                         if(DEBUG&8192) printf("temporary <%s> assigned to %s\n",p->z.v->identifier,regnames[r]);
  792.                     }else BSET(inmem,j);
  793.                 }
  794.             }
  795.             if((p->q1.flags&(VAR|REG|VARADR))==VAR&&!(p->q1.v->flags&USEDASADR)&&!(p->q1.v->vtyp->flags&VOLATILE)&&(p->q1.v->storage_class==AUTO||p->q1.v->storage_class==REGISTER)){
  796.                 j=p->q1.v->index;
  797.                 if(BTST(lfg->av_kill,j)&&!BTST(lfg->av_out,j)&&!BTST(inmem,j)){
  798.                     t=p->q1.v->vtyp->flags;
  799.                     if(nr&®ok(nr,t,0)&&!regu[nr]&&!regsa[nr]&&(!(p->q1.flags&DREFOBJ)||regok(nr,t,p->typf))) r=nr; else r=0;
  800.                     if(p->code==SETRETURN&&p->z.reg&®ok(p->z.reg,t,p->typf)) r=p->z.reg;
  801.                     if(p->q1.v->reg){ r=abs(p->q1.v->reg);if(regu[r]) free_hreg(lfg,p,r,1);}
  802.                     for(i=0;r==0&&i<=MAXR;i++){
  803.                         if(!regu[i]&&!regsa[i]&®ok(i,t,0)) {r=i;break;}
  804.                     }
  805.                     if(r){
  806.                         if(r!=nr) insert_allocreg(lfg,p,FREEREG,r);
  807.                             else mustalloc=0;
  808.                         lregv[r]=p->q1.v;regused[r]=regu[r]=1;
  809.                         if(replace_local_reg(&p->q1)!=r) ierror(0);
  810.                         if((DEBUG&9216)&&*p->q1.v->identifier) printf("temporary <%s> assigned to %s\n",p->q1.v->identifier,regnames[r]);
  811.                         if(DEBUG&8192) printf("temporary <%s> assigned to %s\n",p->q1.v->identifier,regnames[r]);
  812.                     }else BSET(inmem,j);
  813.                 }
  814.             }
  815.             if(p->code==CALL){
  816.                 lfg->calls++;
  817.                 /*  falls Scratchregister bei Funktionsaufruf benutzt   */
  818.                 /*  wird, moeglichst auf ein anderes ausweichen         */
  819.                 for(i=1;i<=MAXR;i++){
  820.                     if(lregv[i]&®scratch[i]&&!lregv[i]->reg)
  821.                         free_hreg(lfg,p,i,0);
  822.                 }
  823.             }
  824.             /*  die Faelle beachten, wenn schon im IC ein Register          */
  825.             /*  angesprochen wird (sollte nur bei CALL und return auftreten */
  826.             if(p->code==FREEREG){
  827.                 ierror(0);
  828.                 if(regu[p->q1.reg]) remove_IC_fg(lfg,p);
  829.                 regu[p->q1.reg]++;
  830.             }
  831.             if(p->code==ALLOCREG){
  832.                 ierror(0);
  833.                 if(regu[p->q1.reg]==2) remove_IC_fg(lfg,p);
  834.                 regu[p->q1.reg]--;
  835.             }
  836.             if(p==lfg->start) i=1; else i=0;;
  837.             p=p->prev;
  838.             if(nr&&mustalloc) insert_allocreg(lfg,p,ALLOCREG,nr);
  839.             if(i) break;
  840.         }
  841.         lfg=lfg->normalout;
  842.     }
  843.     free(inmem);
  844. }
  845. void insert_saves(void)
  846. /*  fuegt speichern von Registern bei Funktionsaufrufen ein */
  847. {
  848.     int i,c;struct IC *p;
  849.     if(DEBUG&9216) printf("insert_saves\n");
  850.     for(i=1;i<=MAXR;i++) regs[i]=regsa[i];
  851.     for(p=first_ic;p;p=p->next){
  852.         c=p->code;
  853.         if(c==ALLOCREG) regs[p->q1.reg]=1;
  854.         if(c==FREEREG)  regs[p->q1.reg]=0;
  855.         if(c==CALL){
  856.             struct IC *s;
  857.             /*  das Wiederherstellen nach dem GETRETURN     */
  858.             s=p; i=0;
  859.             if(s->next&&s->next->code==FREEREG) {s=s->next;regs[s->q1.reg]=0;}
  860.             if(s->next&&s->next->code==GETRETURN){
  861.                 s=s->next;
  862.                 if((s->z.flags&(REG|DREFOBJ))==REG) i=s->z.reg;
  863.             }
  864.             if(s->next&&s->next->code==ALLOCREG&&s->next->next&&s->next->next->code==GETRETURN){
  865.                 s=s->next->next;
  866.                 if((s->z.flags&(REG|DREFOBJ))==REG) i=s->z.reg;
  867.             }
  868.             savescratch(MOVEFROMREG,p->prev,0);
  869.             savescratch(MOVETOREG,s,i);
  870.         }
  871.     }
  872. }
  873.  
  874. #endif
  875.  
  876. void insert_simple_allocreg(struct IC *p,int code,int reg)
  877. /*  Fuegt ein ALLOCREG/FREEREG (in code) hinter p ein - bei p==0 in */
  878. /*  first_ic.                                                       */
  879. {
  880.     struct IC *new=mymalloc(ICS);
  881.     new->line=0;
  882.     new->file=0;
  883.     regused[reg]=1;
  884.     new->code=code;
  885.     new->typf=0;
  886.     new->q1.am=new->q2.am=new->z.am=0;
  887.     new->q1.flags=REG;
  888.     new->q1.reg=reg;
  889.     new->q2.flags=new->z.flags=0;
  890.     new->use_cnt=new->change_cnt=0;
  891.     new->use_list=new->change_list=0;
  892.     insert_IC(p,new);
  893. }
  894.  
  895. void load_simple_reg_parms(void)
  896. /*  Laedt Registerparameter, falls noetig. Nicht-optimierende Version.  */
  897. {
  898.   int i,j; struct Var *v;
  899.   struct regp regp[MAXR+1]={0};
  900. /*   for(i=1;i<=MAXR;i++) {regp[i].treg=0;regp[i].tvar=0;} */
  901.   for(i=0;i<=1;i++){
  902.     if(i==0) v=vl3; else v=vl2;
  903.     for(;v;v=v->next){
  904.       if((v->flags®PARM)&®sv[abs(v->reg)]!=v){
  905.     regp[abs(v->reg)].tvar=v;
  906.     for(j=1;j<=MAXR;j++)
  907.       if(regsv[j]==v) regp[abs(v->reg)].treg=j;
  908.       }
  909.     }
  910.   }
  911.   do_load_parms(regp,0);
  912. }
  913. void do_load_parms(struct regp regp[],struct flowgraph *fg)
  914. {
  915.   int i,j,c,notdone;
  916.   struct {int freg,treg;struct Var *tvar,*tmp;} order[MAXR]={0};
  917.   if(DEBUG&1){
  918.     printf("do_load_parms:\n");
  919.     for(i=1;i<=MAXR;i++)
  920.       if(regp[i].tvar)
  921.     printf("%s->%s(%s)\n",regnames[i],regnames[regp[i].treg],regp[i].tvar->identifier);
  922.   }
  923.   do{
  924.     c=0;
  925.     do{
  926.       notdone=0;
  927.       for(i=1;i<=MAXR;i++){
  928.     if(!regp[i].tvar) continue;
  929.     j=regp[i].treg;
  930.     if(j==0||regp[j].tvar==0||regp[i].tmp){
  931.       order[c].freg=i;
  932.       order[c].treg=j;
  933.       order[c].tvar=regp[i].tvar;
  934.       if(regp[i].tmp){order[c].treg=0;order[c].tvar=regp[i].tmp;}
  935.       c++; notdone=1;
  936.       regp[i].treg=0;
  937.       regp[i].tvar=0;
  938.     }
  939.       }
  940.     }while(notdone);
  941.     for(i=c-1;i>=0;i--)
  942.       load_one_parm(order[i].freg,order[i].treg,0,order[i].tvar,fg);
  943.     notdone=0;
  944.     for(i=1;i<=MAXR;i++){
  945.       if(regp[i].tvar){
  946.     regp[i].tmp=add_tmp_var(clone_typ(regp[i].tvar->vtyp));
  947.     load_one_parm(0,regp[i].treg,regp[i].tmp,regp[i].tvar,fg);
  948.     notdone=1; break;
  949.       }
  950.     }
  951.   }while(notdone);
  952. }
  953. void load_one_parm(int freg,int treg,struct Var *fvar,struct Var *tvar,struct flowgraph *fg)
  954. {
  955.   struct IC *new;
  956.   if(DEBUG&1) printf("lop: %s(%s)->%s(%s)\n",regnames[freg],fvar?fvar->identifier:empty,regnames[treg],tvar?tvar->identifier:empty);
  957.   if(freg){
  958.     if(fg)
  959.       insert_allocreg(fg,0,FREEREG,freg);
  960.     else
  961.       insert_simple_allocreg(0,FREEREG,freg);
  962.   }
  963.   new=mymalloc(ICS);
  964.   new->line=0;
  965.   new->file=0;
  966.   new->code=ASSIGN;
  967.   new->typf=tvar->vtyp->flags;
  968.   if((new->typf&NQ)==FLOAT||(new->typf&NQ)==DOUBLE) float_used=1;
  969.   if(fvar){
  970.     new->q1.flags=VAR;
  971.     new->q1.v=fvar;
  972.     new->q1.val.vlong=l2zl(0L);
  973.   }else{
  974.     new->q1.flags=REG;
  975.     new->q1.reg=freg;
  976.   }
  977.   new->q2.flags=0;
  978.   new->q2.val.vlong=szof(tvar->vtyp);
  979.   if(treg)
  980.     new->z.flags=REG|VAR;
  981.   else
  982.     new->z.flags=VAR;
  983.   new->z.val.vlong=l2zl(0L);
  984.   new->z.v=tvar;
  985.   new->z.reg=treg;
  986.   new->q1.am=new->q2.am=new->z.am=0;
  987.   new->use_cnt=new->change_cnt=0;
  988.   new->use_list=new->change_list=0;
  989.   if((new->typf&NQ)==CHAR&&!regok(new->q1.reg,new->typf,0))
  990.     new->code=CONVINT;
  991.   if(fg){
  992.     insert_IC_fg(fg,0,new);
  993.     if(freg) insert_allocreg(fg,0,ALLOCREG,freg);
  994.   }else{
  995.     insert_IC(0,new);
  996.     if(freg) insert_simple_allocreg(0,ALLOCREG,freg);
  997.   }
  998.   if(new->z.flags®){
  999.     /*  ALLOCREG verschieben    */
  1000.     struct IC *p;
  1001.     if(fg)
  1002.       insert_allocreg(fg,0,ALLOCREG,treg);
  1003.     else
  1004.       insert_simple_allocreg(0,ALLOCREG,treg);
  1005.     for(p=new->next;p;p=p->next){
  1006.       if(p->code==ALLOCREG&&p->q1.reg==treg){
  1007.     if(fg)
  1008.       remove_IC_fg(fg,p);
  1009.     else
  1010.       remove_IC(p);
  1011.     break;
  1012.       }
  1013.     }
  1014.     if(!p) ierror(0);
  1015.   }
  1016. }
  1017.  
  1018. void simple_regs(void)
  1019. /*  haelt Variablen in Registern, simple Version            */
  1020. {
  1021.     int i2,i,j;int pri;struct Var *v;
  1022.     struct IC *icp,*start=first_ic;
  1023.     if(!first_ic) return;
  1024.     for(i=1;i<=MAXR;i++) regsv[i]=0;
  1025.     for(i2=0;i2<=MAXR*4;i2++){
  1026.         int only_best,pointertype;
  1027.         if(i2<=MAXR*2){i=i2;only_best=1;} else {i=i2/2;pointertype=only_best=0;}
  1028.         if(i>MAXR||!regsv[i]){
  1029.             if(i>MAXR){
  1030.                 i-=MAXR;
  1031.                 if(regsv[i]) continue;
  1032.             }else{
  1033.                 /*  Ziehe Scratchregister vor, wenn kein Funktionsaufruf */
  1034.                 /*  erfolgt, sonst erst andere                           */
  1035.                 if(!function_calls&&!regscratch[i]) continue;
  1036.                 if(function_calls&®scratch[i]) continue;
  1037.             }
  1038.             if(regused[i]) continue;
  1039.             /* Nicht-Scratchregister muessen einmal gesichert und wieder    */
  1040.             /* hergestellt werden, Scratchregister bei jedem Call           */
  1041.             if(regscratch[i]&&function_calls) continue;
  1042.             /*pri=2;*/ pri=0;
  1043.             for(j=0;j<=1;j++){
  1044.                 if(j==0) v=vl3; else v=vl2;
  1045.                 while(v){
  1046.                     if(v->storage_class==AUTO||v->storage_class==REGISTER){
  1047.                         if(!(v->flags&USEDASADR)&&!(v->vtyp->flags&VOLATILE)){
  1048.                             if(only_best&&v->vtyp->next) pointertype=v->vtyp->next->flags;
  1049.                             if(v->priority>pri&®ok(i,v->vtyp->flags&NU,pointertype)){
  1050.                                 regsv[i]=v;pri=v->priority;
  1051.                             }
  1052.                         }
  1053.                     }
  1054.                     v=v->next;
  1055.                 }
  1056.             }
  1057.         }
  1058.         if(regsv[i]){
  1059.             if(DEBUG&1) printf("Assigned <%s> to %s\n",regsv[i]->identifier,regnames[i]);
  1060.             regsv[i]->priority=0;regused[i]=1;
  1061.             if(!zlleq(l2zl(0L),regsv[i]->offset)&&!(regsv[i]->flags&(CONVPARAMETER|REGPARM))){
  1062.                 icp=mymalloc(ICS);
  1063.                 icp->line=0;
  1064.                 icp->file=0;
  1065.                 icp->q1.am=icp->q2.am=icp->z.am=0;
  1066.                 icp->code=ASSIGN;
  1067.                 icp->typf=regsv[i]->vtyp->flags&NU;
  1068.                 icp->q1.flags=VAR;
  1069.                 icp->q1.v=regsv[i];
  1070.                 icp->q1.val.vlong=l2zl(0L);
  1071.                 icp->q2.flags=0;
  1072.                 icp->q2.val.vlong=szof(regsv[i]->vtyp);
  1073.                 icp->z.flags=REG;
  1074.                 icp->z.reg=i;
  1075.                 icp->next=first_ic;
  1076.                 icp->prev=0;
  1077.                 first_ic->prev=icp;
  1078.                 first_ic=icp;
  1079.             }
  1080.             icp=mymalloc(ICS);
  1081.             icp->line=0;
  1082.             icp->file=0;
  1083.             icp->q1.am=icp->q2.am=icp->z.am=0;
  1084.             icp->code=ALLOCREG;
  1085.             icp->q1.flags=REG;
  1086.             icp->q1.reg=i;
  1087.             icp->q2.flags=icp->z.flags=icp->typf=0;
  1088.             icp->next=first_ic;
  1089.             icp->prev=0;
  1090.             first_ic->prev=icp;
  1091.             first_ic=icp;
  1092.             icp=mymalloc(ICS);
  1093.             icp->q1.am=icp->q2.am=icp->z.am=0;
  1094.             icp->code=FREEREG;
  1095.             icp->q1.flags=REG;
  1096.             icp->q1.reg=i;
  1097.             icp->q2.flags=icp->z.flags=icp->typf=0;
  1098.             icp->next=0;
  1099.             add_IC(icp);
  1100.         }
  1101.     }
  1102.     icp=start;
  1103.     while(icp){
  1104.         if((icp->code==ALLOCREG||icp->code==FREEREG)&®sv[icp->q1.reg]){
  1105.         /*  irgendwelche allocreg/freereg im Code entfernen     */
  1106.         /*  sollte nur beim Returnregister vorkommen            */
  1107.             struct IC *m=icp->next;
  1108.             remove_IC(icp);
  1109.             icp=m;continue;
  1110.         }
  1111.         for(i=1;i<=MAXR;i++){
  1112.             if(!regsv[i]) continue;
  1113.             if((icp->q1.flags&(VAR|DONTREGISTERIZE))==VAR&&icp->q1.v==regsv[i]){
  1114.                 icp->q1.flags|=REG;
  1115.                 icp->q1.reg=i;
  1116.             }
  1117.             if((icp->q2.flags&(VAR|DONTREGISTERIZE))==VAR&&icp->q2.v==regsv[i]){
  1118.                 icp->q2.flags|=REG;
  1119.                 icp->q2.reg=i;
  1120.             }
  1121.             if((icp->z.flags&(VAR|DONTREGISTERIZE))==VAR&&icp->z.v==regsv[i]){
  1122.                 icp->z.flags|=REG;
  1123.                 icp->z.reg=i;
  1124.             }
  1125.         }
  1126.         icp=icp->next;
  1127.     }
  1128. }
  1129.  
  1130.  
  1131.